package client;

import java.io.IOException;
import java.util.HashMap;
import util.ConfReader;
import network.TeamCurator;

/**
 * Собственно клиент (Волшебный код от Коста). 
 * Ему нужны 2 конфига вида Key=Value (teams.txt и config.txt)
 * teams.txt содержит строки вида "имя команды=A.B.C.", 
 * где A, B, C - первых 3 числа в адресе уязвимой машины.
 * config.txt содержит строки с названиями и значениями статических полей TeamCurator'а
 * Запускает по потоку TeamCurator на каждую команду и периодически перезапускает их.
 */

public class Moderator extends Thread {

	
//------------- CONSTANTS, GLOBAL VARS -----------
	
	public static String configFileName = "config.txt";
	public static String teamsConfigFileName = "teams.txt";
	public static int ERROR_CONFIG = 1;
	public static int deadThreadsCheckCycleLength = 10000; //time to check all threads
	
//------------------------------------------------
	
	private HashMap<String, String> teams;
	TeamCurator[] curators;
	
	
	
	public static void main(String[] args) {
		Moderator moderator = new Moderator();
		moderator.start();
	}
	/**
	 * Считывает конфиги из configs.txt и teams.txt. 
	 * Умирает в случае битых конфигов, выдает номер плохой строки.
	 * После прочтения конфигов запускает TeamCurator на каждую команду.
	 */
	@Override
	public void start(){
		ConfReader cReader = new ConfReader(teamsConfigFileName);
		try {
			teams = cReader.read();
		} 
		catch (IOException e) {
			System.err.println("ERROR! In parsing " + teamsConfigFileName);
			System.exit(ERROR_CONFIG);
		}
		catch(Exception e){
			System.err.println("ERROR! In parsing " + teamsConfigFileName);
			System.err.println(e.getMessage());
			System.exit(ERROR_CONFIG);
		}
		
		
		HashMap<String, String> config = null;
		cReader = new ConfReader(configFileName);
		try {
			config = cReader.read();
		} catch (IOException e) {
			System.err.println("ERROR! In parsing " + configFileName);
			System.err.println(e.getMessage());
			System.exit(ERROR_CONFIG);
		}
		catch(Exception e){
			System.err.println("ERROR! In parsing " + configFileName);
			System.err.println(e.getMessage());
			System.exit(ERROR_CONFIG);
		}
		
		applyConfig(config);
		
		if (teams.size() > 0){
		
			curators = new TeamCurator[teams.size()];
			
			int i = 0;
			for(String teamName : teams.keySet()){
				curators[i] = new TeamCurator(teams.get(teamName), teamName);
				curators[i].setDaemon(true);
				curators[i++].start();	
			}
			
			
					
			for (int n=0; true; n++ ){
				n = n % teams.size();
				if (!curators[n].isAlive()){
					String teamName = curators[n].teamName;
					curators[n] = new TeamCurator(teams.get(teamName), teamName);
					curators[n].setDaemon(true);
					curators[n].start();
				}
				try {
					sleep(deadThreadsCheckCycleLength / teams.size());
				} catch (InterruptedException e) {
					System.err.println("Moderator was interrupted when sleeping! What does it mean?");
					System.err.println(e.getMessage());
				}
			}
		
		
		}
		else{
			System.err.println("WARNING! No valid teams in " + teamsConfigFileName);
		}
	}
	
	/**
	 * Инициализирует статические поля TeamCurator'a, 
	 * про которые уточняется в конфигах
	 */

	private void applyConfig(HashMap<String, String> config) {
		if (config.containsKey("exploitFileName"))
			TeamCurator.exploitFileName = config.get("exploitFileName");
		if (config.containsKey("exploitName")){
			TeamCurator.exploitName = config.get("exploitName");
			TeamCurator.logFileName = "logs/" + TeamCurator.exploitName + ".txt";
		}
		if (config.containsKey("efServerIp"))
			TeamCurator.efServerIp = config.get("efServerIp");
		if (config.containsKey("efServerPort"))
			TeamCurator.efServerPort = Integer.parseInt(config.get("efServerPort"));
		if (config.containsKey("vulnBoxSuff"))
			TeamCurator.vulnBoxSuff = config.get("vulnBoxSuff");
		if (config.containsKey("exploitRestartDelay"))
			TeamCurator.exploitRestartDelay = Integer.parseInt(config.get("exploitRestartDelay"));
		if (config.containsKey("flagWaitDelay"))
			TeamCurator.flagWaitDelay = Integer.parseInt(config.get("flagWaitDelay"));
		if (config.containsKey("timesToWaitFlag"))
			TeamCurator.timesToWaitFlag = Integer.parseInt(config.get("timesToWaitFlag"));
		
		
		if (config.containsKey("deadThreadsCheckCycleLength"))
			deadThreadsCheckCycleLength = Integer.parseInt(config.get("deadThreadsCheckCycleLength"));
		
	}

}
